﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Cms.Application.Admin.Views;
using Cms.Application.IO;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.RepositoryInterfaces;
using Cms.Utilities;
using iLib.Web.UI;

namespace Cms.Application.Admin.Presenters
{
    public class EditCustomAdminPagePresenter : BasePresenter
    {
        private readonly IEditCustomAdminPageView _view;

        public IDiskAccess DiskAccess { get; set; }

        protected Administrator Administrator { get; set; }

        public EditCustomAdminPagePresenter(IEditCustomAdminPageView view)
            : this(view, new RepositoryFactory())
        {
            DiskAccess = new DiskAccess();
        }

        public EditCustomAdminPagePresenter(IEditCustomAdminPageView view, IRepositoryFactory repositoryFactory)
            : base(view, repositoryFactory)
        {
            _view = view;
            Administrator = AdministratorRepository.GetAdministrator(_view.AdministratorID);
            if (!Administrator.HasPermission.EditCustomAdminPage)
                _view.RedirectToPermissionDeniedPage();
        }

        public void Initialize()
        {
            if (_view.CustomAdminPageId == -1)
            {
                _view.Code = DiskAccess.ReadTextFile("Admin\\Resources\\NewCustomAdminPageTemplate.aspx");
                _view.XmlTranslations = DiskAccess.ReadTextFile("Admin\\Resources\\NewCustomAdminPageTranslationsTemplate.xml");
            }
            else
            {
                RefreshPropertiesOnView();
                CustomAdminPage customAdminPage = SystemRepository.GetCustomAdminPage(_view.CustomAdminPageId);
                _view.Code = customAdminPage.GetCode();
                _view.XmlTranslations = customAdminPage.GetXmlTranslations();
            }
            SaveSourceCodePreview();
        }

        public void Validate()
        {
            if (_view.CurrentTab != "properties")
            {
                return;
            }
            if (_view.Name.Trim() == string.Empty)
            {
                AddValidationError(1, GetText(_view, "NoNameError"));
            }
            if (_view.Filename.Trim() == string.Empty)
            {
                AddValidationError(2, GetText(_view, "NoFilenameError"));
            }
            else
            {
                if (SystemRepository.CustomAdminPageFilenameExists(_view.CustomAdminPageId, _view.Filename + ".aspx"))
                {
                    AddValidationError(3, GetText(_view, "FilenameCollisionError"));
                }
                if (!RegexValidation.NameIsFileSystemCompliant(_view.Filename.Trim()))
                {
                    AddValidationError(4, GetText(_view, "NameNotFileSystemCompliantError"));
                }
            }
            string filename = _view.Filename;
            if (!filename.ToLower().EndsWith(".aspx"))
            {
                filename += ".aspx";
            }
            if (_view.CurrentTab != "xmlTranslations" && _view.CurrentTab != "code")
            {
                return;
            }
            SaveSourceCodePreview();
            string sourceCodeValidationResult = _view.GetSourceCodeStatus();
            if (sourceCodeValidationResult == "ok")
            {
                return;
            }
            string errorText = GetText(_view, "SourceCodeError");
            errorText = errorText.Replace("[[ErrorMessage]]", sourceCodeValidationResult);
            string encryptedCredentials = Cipher.Encrypt(Administrator.Username + (char)9 + Administrator.Password);
            string url = Url.FullPath + "Admin/Default.aspx?credentials=" +
                         HttpUtility.UrlEncode(encryptedCredentials) + "&ReturnUrl=" +
                         HttpUtility.UrlEncode(_view.UserTempDirectory + "ErrorDetails.aspx?v=" + DateTime.Now.Ticks);
            errorText = errorText.Replace("[[ErrorDetailsUrl]]", url);
            AddValidationError(errorText);
        }

        public void Save()
        {
            Validate();
            if (!IsValid)
            {
                return;
            }
            CustomAdminPage page = _view.CustomAdminPageId == -1
                            ? new CustomAdminPage { Site = Administrator.CurrentSite }
                            : SystemRepository.GetCustomAdminPage(_view.CustomAdminPageId);
            GetPropertiesFromView(page);
            SystemRepository.SaveCustomAdminPage(page);
            SaveCode(page);
            SaveXmlTranslations(page);
            SystemRepository.SaveCustomAdminPage(page);
            _view.SetCustomAdminPageId(page.Id);
        }

        public void SaveSourceCodePreview()
        {
            CustomAdminPage customAdminPage = SystemRepository.GetCustomAdminPage(_view.CustomAdminPageId);
            if (customAdminPage == null)
            {
                return;
            }
            string code = _view.Code;
            if (!code.EndsWith(Environment.NewLine))
            {
                code += Environment.NewLine;
            }
            DiskAccess.DeleteFile(_view.UserPhysicalTempDirectory + "\\CustomAdminPagePreview.aspx");
            DiskAccess.CreateTextFile(_view.UserPhysicalTempDirectory + "\\CustomAdminPagePreview.aspx", code);
        }

        private void SaveCode(CustomAdminPage customAdminPage)
        {
            customAdminPage.SetCode(_view.Code, Administrator);
            string code = _view.Code;
            if (!code.EndsWith(Environment.NewLine))
            {
                code += Environment.NewLine;
            }
            DiskAccess.CreateDirectory("__System\\CustomAdminPages");
            DiskAccess.DeleteFile("__System\\CustomAdminPages\\" + customAdminPage.Filename);
            DiskAccess.CreateTextFile("__System\\CustomAdminPages\\" + customAdminPage.Filename, code);
        }

        private void SaveXmlTranslations(CustomAdminPage customAdminPage)
        {
            customAdminPage.SetXmlTranslations(_view.XmlTranslations, Administrator);
            string xmlTranslations = _view.XmlTranslations;
            if (!xmlTranslations.EndsWith(Environment.NewLine))
            {
                xmlTranslations += Environment.NewLine;
            }
            DiskAccess.CreateDirectory("__System\\CustomAdminPages");
            string xmlFilename = System.IO.Path.GetFileNameWithoutExtension(customAdminPage.Filename) + ".xml";
            DiskAccess.DeleteFile("__System\\CustomAdminPages\\" + xmlFilename);
            DiskAccess.CreateTextFile("__System\\CustomAdminPages\\" + xmlFilename, xmlTranslations);
        }

        public void UpdateHeading()
        {
            _view.HeadingText = _view.CustomAdminPageId > 0
                                    ? GetText(_view, "EditPageHeading") + " &mdash; " + _view.Name
                                    : GetText(_view, "NewPageHeading");
        }

        public void SetAdministratorGroupPermissions()
        {
            _view.SetAllowedAdministratorGroups(
                AdministratorRepository.GetCustomGroups(),
                new List<AdministratorGroup>(), 
                _view.GetSelectedAllowedAdministratorGroups().ToList());
            _view.SetDeniedAdministratorGroups(
                AdministratorRepository.GetCustomGroups(),
                new List<AdministratorGroup>(),
                _view.GetSelectedDeniedAdministratorGroups().ToList());

        }
        
        public void RefreshPropertiesOnView()
        {
            if (_view.CustomAdminPageId < 0)
            {
                return;
            }
            CustomAdminPage customAdminPage = SystemRepository.GetCustomAdminPage(_view.CustomAdminPageId);
            _view.Filename = customAdminPage.Filename.Substring(0, customAdminPage.Filename.Length - 5); // Remove ".aspx"
            _view.Name = customAdminPage.Name;
            _view.ShowInMenu = customAdminPage.ShowInMenu;
            _view.SetAllowedAdministratorGroups(
                AdministratorRepository.GetCustomGroups(), 
                new List<AdministratorGroup>(), 
                customAdminPage.AllowedAdministratorGroups);
            _view.SetDeniedAdministratorGroups(
                AdministratorRepository.GetCustomGroups(), 
                new List<AdministratorGroup>(), 
                customAdminPage.DeniedAdministratorGroups);
        }

        public void GetPropertiesFromView(CustomAdminPage customAdminPage)
        {
            customAdminPage.Filename = _view.Filename;
            if (!customAdminPage.Filename.ToLower().EndsWith(".aspx"))
            {
                customAdminPage.Filename += ".aspx";
            }
            customAdminPage.Name = _view.Name;
            customAdminPage.ShowInMenu = _view.ShowInMenu;
            foreach (AdministratorGroup group in customAdminPage.AllowedAdministratorGroups)
            {
                group.AllowedCustomAdminPages.Remove(customAdminPage);
            }
            customAdminPage.AllowedAdministratorGroups.Clear();
            foreach (AdministratorGroup group in _view.GetSelectedAllowedAdministratorGroups())
            {
                customAdminPage.AllowedAdministratorGroups.Add(group);
                group.AllowedCustomAdminPages.Add(customAdminPage);
            }
            foreach (AdministratorGroup group in customAdminPage.DeniedAdministratorGroups)
            {
                group.DeniedCustomAdminPages.Remove(customAdminPage);
            }
            customAdminPage.DeniedAdministratorGroups.Clear();
            foreach (AdministratorGroup group in _view.GetSelectedDeniedAdministratorGroups())
            {
                customAdminPage.DeniedAdministratorGroups.Add(group);
                group.DeniedCustomAdminPages.Add(customAdminPage);
            }
        }
    }
}